package com.songcan.oauth.point;

import com.songcan.common.contans.CoreContants;
import com.songcan.common.vo.CoreResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.security.oauth2.provider.error.AbstractOAuth2SecurityExceptionHandler;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 令牌校验器
 */
@Service
@Slf4j
public class CoreAuthenticationEntrePoint extends AbstractOAuth2SecurityExceptionHandler implements AuthenticationEntryPoint {

    private String typeName = "Bearer";
    private String realmName = "oauth";

    public CoreAuthenticationEntrePoint() {
    }

    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
        this.doHandle(request, response, authException);
    }

    @Transactional
    protected ResponseEntity<OAuth2Exception> enhanceResponse(ResponseEntity<?> response, Exception exception) {
        HttpHeaders headers = response.getHeaders();
        String existing = null;
        if (headers.containsKey("WWW-Authenticate")) {
            existing = this.extractTypePrefix(headers.getFirst("WWW-Authenticate"));
        }

        StringBuilder builder = new StringBuilder();
        builder.append(this.typeName + " ");
        builder.append("realm=\"" + this.realmName + "\"");
        if (existing != null) {
            builder.append(", " + existing);
        }
        HttpHeaders update = new HttpHeaders();
        update.putAll(response.getHeaders());
        update.set("WWW-Authenticate", builder.toString());
        CoreResult webAccessResult = new CoreResult();
        webAccessResult.setCode(CoreContants.ERROR_TOKEN_INVALID);
        if (response.getBody().toString().contains("error") && response.getBody().toString().contains("invalid_token")) {
            webAccessResult.setMsg("您的令牌过期了");
        } else {
            webAccessResult.setMsg(existing);
        }
        log.error("token解析错误:{}", existing);

        return new ResponseEntity(webAccessResult, update, HttpStatus.OK);
    }

    private String extractTypePrefix(String header) {
        String existing = header;
        String[] tokens = header.split(" +");
        if (tokens.length > 1 && !tokens[0].endsWith(",")) {
            existing = StringUtils.arrayToDelimitedString(tokens, " ").substring(header.indexOf(" ") + 1);
        }

        return existing;
    }
}
